package com.softdev.system.generator.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.comments.Comment;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.expr.SimpleName;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.ast.visitor.VoidVisitor;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import com.softdev.system.generator.entity.ClassInfo;
import com.softdev.system.generator.entity.FieldInfo;
import com.softdev.system.generator.entity.ParamInfo;

public class JavaBeanParserUtils {

	public static ClassInfo processJavaIntoClassInfo(ParamInfo paramInfo) throws IOException {
		InputStream is = new ByteArrayInputStream(paramInfo.getTableSql().getBytes());

		return parserJava(is);
	}

	public static ClassInfo parserJava(InputStream inputStream) {
		CompilationUnit compilationUnit = StaticJavaParser.parse(inputStream);
		String className = getClassName(compilationUnit);
		String classComment = getClassComment(compilationUnit);
		List<FieldInfo> fieldList = parserJava(compilationUnit.findAll(FieldDeclaration.class));
//		List<FieldInfo> maxParamConsFieldList = getConstructor(compilationUnit);

		ClassInfo codeJavaInfo = new ClassInfo();
		codeJavaInfo.setTableName(className);
		codeJavaInfo.setClassName(className);
		codeJavaInfo.setClassComment(classComment);
		codeJavaInfo.setFieldList(fieldList);
		codeJavaInfo.setOriginTableName(className);

		return codeJavaInfo;

	}

	private static List<FieldInfo> parserJava(List<FieldDeclaration> list) {
		List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
		for (FieldDeclaration f : list) {
			FieldInfo field = parserJava(f);
			if (!field.getFieldName().equals("serialVersionUID")) {
				fieldList.add(field);
			}
		}
		return fieldList;
	}

	private static FieldInfo parserJava(FieldDeclaration fieldDeclaration) {
		// 注释
		String comment = getComment(fieldDeclaration);

		// 类型
		Type elementType = fieldDeclaration.getElementType();
		// 名称
		SimpleName name = fieldDeclaration.getVariables().get(0).getName();
		// 注解
		NodeList<AnnotationExpr> annotations = fieldDeclaration.getAnnotations();
		Set<String> set = new HashSet<>();
		for (AnnotationExpr annotationExpr : annotations) {
			set.add(annotationExpr.toString().replaceAll(" ", ""));
		}

		String className = name.toString();
		FieldInfo fieldInfo = new FieldInfo();
		fieldInfo.setColumnName(className);
		fieldInfo.setFieldName(className);
		fieldInfo.setFieldClass(elementType.toString());
		fieldInfo.setSwaggerClass(className);
		fieldInfo.setFieldComment(comment);
		fieldInfo.setAnnotations(set);

		return fieldInfo;
	}

	private static String getComment(Parameter parameter) {

		Optional<Comment> commentOptional = parameter.getComment();
		if (!commentOptional.isPresent()) {
			return "";
		}
		Comment comment = commentOptional.get();
		String result = comment.getContent();
		return result.replaceAll("(\r\n|\r|\n|\n\r|\\*|/)", "").trim();
	}

	private static String getComment(FieldDeclaration fieldDeclaration) {

		Optional<Comment> commentOptional = fieldDeclaration.getComment();
		if (!commentOptional.isPresent()) {
			return "";
		}
		Comment comment = commentOptional.get();
		String result = comment.getContent();
		return result.replaceAll("(\r\n|\r|\n|\n\r|\\*|/)", "").trim();
	}

	private static String getClassComment(CompilationUnit compilationUnit) {
		Optional<ClassOrInterfaceDeclaration> optional = compilationUnit.findFirst(ClassOrInterfaceDeclaration.class);
		if (!optional.isPresent()) {
			return "";
		}
		ClassOrInterfaceDeclaration classDeclaration = optional.get();
		Optional<Comment> optionalComment = classDeclaration.getComment();
		if (!optionalComment.isPresent()) {
			return "";
		}
		Comment comment = optionalComment.get();
		String result = comment.getContent().replaceAll("(\r\n|\r|\n|\n\r|\\*|/)", "").trim();
		int endIndex = result.indexOf(" ");
		if (endIndex < 0) {
			endIndex = result.length();
		}
		return result.substring(0, endIndex);
	}

	private static String getClassName(CompilationUnit compilationUnit) {
		List<String> className = new ArrayList<>();
		VoidVisitor<List<String>> classNameVisitor = new ClassNameCollector();
		classNameVisitor.visit(compilationUnit, className);
		return className.get(0);
	}

	public static class ClassNameCollector extends VoidVisitorAdapter<List<String>> {
		@Override
		public void visit(ClassOrInterfaceDeclaration n, List<String> collector) {
			super.visit(n, collector);
			collector.add(n.getNameAsString());
		}
	}
}
